#ifndef UdpServer_h
#define UdpServer_h
#include <iostream>
#include <string>
#include <memory>
#include <cstring>
// 套接字四件套
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <functional>
#include "Threadpool.hpp"
#include "Use.hpp"

#define CONV(v) (struct sockaddr *)(v)

using namespace std;

static int gsockfd = -1;
const string gdefauttip = "47.109.203.137";
const static uint16_t gdefaultport = 8888;

using send_t = function<void(int sockfd, const std::string &message)>;
using useradd_t = function<bool(InterAddr &addr)>;
using task_t = function<void()>;
class UdpServer
{
public:
    UdpServer(send_t sendmessage, useradd_t useradd, uint16_t port = gdefaultport)
        : _socketfd(gsockfd), _port(port), _isrunning(false)
    {
        _sendmessage = sendmessage;
        _useradd = useradd;
    }
    void Init() // 套接字初始化
    {
        _socketfd = socket(AF_INET, SOCK_DGRAM, 0); // 选择网络还是本地
        if (_socketfd < 0)                          // 如果为-1表示创建失败
        {
            cout << "创建套接字失败" << endl;
            exit(-1);
        }
        // 地址初始化
        // struct sockaddr_in local;
        InterAddr addr(gdefaultport);// 自定义soketaddr
    
        // bzero(&local, sizeof(local));
        // local.sin_family = AF_INET;
        // local.sin_port = htons(_port);                                     // 主机转网络端口
        // local.sin_addr.s_addr = INADDR_ANY;                                // 主机转网络ip
        int n = bind(_socketfd, addr.NetAddr(), addr.NetAddrLen()); // 绑定套接字与地址
        if (n == -1)
        {
            perror("1111");
            cout << "绑定失败" << endl;
        }
        cout << "bind sucess";
    }

    void Start()
    {
        _isrunning = true;

        while (true)
        {
            char buffer[1024];
            int defaultsize = 1024;
            struct sockaddr_in client;
            socklen_t sockaddrlen = sizeof(client);
            int n = recvfrom(_socketfd, buffer, defaultsize, 0, CONV(&client), &sockaddrlen); // 接收消息--0为阻塞等待
            if (n > 0)
            {
                uint16_t clientport = ntohs(client.sin_port);
                string clientip = inet_ntoa(client.sin_addr);
                buffer[n] = 0;
                string temp = buffer;
                InterAddr clien(client);

                _useradd(clien);         //每次进来之后判断用户是否在内
                //_sendmessage(_socketfd,temp);
                Threadpool<task_t> *poo = Threadpool<task_t>::Getptr();
                poo->Init();
                poo->Start();
                
                int tempsocktfd=_socketfd;
                send_t tempsend=_sendmessage;
                poo->Equeue([tempsocktfd,temp,tempsend]()->void{tempsend(tempsocktfd,temp);});
                poo->Stop();
                poo->Wait();
                LOG(LogLevel::INFO)<<clientip<<"端口:"<<clientport<<temp;
                // cout<<"来自ip->"<<clientip<<"端口号->"<<clientport<<"消息:";
                // cout<<buffer<<endl;
                // string echo="echo#";
                // echo+="zgnb";
                // sendto(_socketfd,echo.c_str(),echo.size(),0,CONV(&client),sizeof(client));
            }
        }
        _isrunning = false;
    }

private:
    send_t _sendmessage;    // 返回信息函数
    useradd_t _useradd;     //添加用户函数
    uint16_t _port;         //端口
    // string _ip;
    int _socketfd; // 创建的sokect的文件描述符
    bool _isrunning;
};
#endif